#include "StdAfx.h"
#include "eventNotification.h"


namespace DSP
{
	namespace
	{
		unsigned int __stdcall eventService(void* pArguments)
		{	
			eventNotification* eventNotif = (eventNotification*)pArguments;
			try
			{
				const int COUNT_HANDLES = 2;
				HANDLE handles[COUNT_HANDLES] = 
				{
					eventNotif->getGraphEventHandle(),
					eventNotif->getStopNotifHandle()
				};
				DWORD object = -1;
				do
				{
					object = WaitForMultipleObjects(COUNT_HANDLES, handles, false, INFINITE);
					switch(object)
					{
					case WAIT_OBJECT_0:
						eventNotif->sendingEvent();
						break;
					case WAIT_FAILED:
						throw std::exception("Wait function has failed.");
					}
				}
				while(object == WAIT_OBJECT_0);
			}
			catch(const std::exception& ex)
			{
				eventNotif->signallingErrorOccur(ex);
			}
			return 0;
		}
	}


	eventNotification::eventNotification(ATL::CComPtr<IMediaEvent>& Event, pFunc_void_long funcEventProcess, pFunc_void_rConstException funcErrorProcess) : 
		pEvent(Event)
	{
		HRESULT hr = pEvent->GetEventHandle((OAEVENT*)&hGraphEvent);
		if(FAILED(hr))
			throw errorInfo("Error: Can not get event handle.", hr);
		sigEventOccur.connect(funcEventProcess);
		sigErrorOccur.connect(funcErrorProcess);
		if(!eStopNotif.Create(NULL, true, false, NULL))
			throw std::exception("Error: Can not create event.");
	}


	eventNotification::~eventNotification(void)
	{
	}


	void eventNotification::startEventNotification(void)
	{
		HANDLE h = (HANDLE)_beginthreadex(NULL, 0, &eventService, (void*)this, 0, NULL);
		if(h == NULL)
			throw std::exception("Error: Can not create thread.");
		else
			hThread.Attach(h);
	}


	void eventNotification::stopEventNotification(void)
	{
		if(!eStopNotif.Set())
			throw std::exception("Error: Can not set event.");
		DWORD code = WaitForSingleObject(hThread.m_h, INFINITE);
		if(code == WAIT_FAILED)
			throw std::exception("Error: Wait function has failed.");
	}


	void eventNotification::sendingEvent(void)
	{
		long evCode = 0;
		LONG_PTR param1 = 0, param2 = 0;
		HRESULT hr = pEvent->GetEvent(&evCode, &param1, &param2, 0);
		if(FAILED(hr))
			throw errorInfo("Error: Can not get event.", hr);
		sigEventOccur(evCode);
		hr = pEvent->FreeEventParams(evCode, param1, param2);
		if(FAILED(hr))
			throw errorInfo("Error: Can not free event parameters.", hr);
	}


	void eventNotification::signallingErrorOccur(const std::exception& ex)
	{
		sigErrorOccur(ex);
	}


	HANDLE eventNotification::getStopNotifHandle(void)
	{
		return eStopNotif.m_h;
	}


	HANDLE eventNotification::getGraphEventHandle(void)
	{
		return hGraphEvent;
	}
}